﻿using System.Collections.Generic;
using Baula.TextGen.Framework.Sections;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Baula.TextGen.Framework.Tests
{
    [TestClass]
    public class DocumentTemplateTests
    {
        [TestMethod]
        public void DefaultCtor_WhenCalled_GivesEmtpyContent()
        {
            var documentTemplate = new DocumentTemplate();

            Assert.AreEqual("", documentTemplate.Content);
        }

        [TestMethod]
        public void Content_WhenSetToSomeNonEmptyString_ReturnsThatString()
        {
            const string content = "Some\r\ncool\r\n\r\ncontent";

            var documentTemplate = new DocumentTemplate();
            documentTemplate.Content = content;

            Assert.AreEqual(content, documentTemplate.Content);
        }

        [TestMethod]
        public void Ctor_WhenCalledWithNonEmptyString_ReturnsThatStringAsContent()
        {
            const string content = "Some\r\ncool\r\nr\\ancontent";

            var documentTemplate = new DocumentTemplate(content);

            Assert.AreEqual(content, documentTemplate.Content);
        }

        [TestMethod]
        public void Content_UsedToSetLiteralContent_GivesThatContent()
        {
            const string content = "Some\r\ncool\r\n\r\ncontent";

            var documentTemplate = new DocumentTemplate();
            documentTemplate.Content = content;

            Assert.AreEqual(content, documentTemplate.MainContent);
        }

        [TestMethod]
        public void Placeholders_WithLiteralTemplate_Finds0Placeholders()
        {
            var documentTemplate = new DocumentTemplate(@"This is literal line
this is another one
and this is the last one");

            Assert.AreEqual(0, documentTemplate.Placeholders.Count);
        }

        [TestMethod]
        public void Placeholders_With1Placeholder1Time_Finds1Placeholders()
        {
            var documentTemplate = new DocumentTemplate(@"This is literal line
this is %ThePlaceholder%, dude!
This is the last line.");

            Assert.AreEqual(1, documentTemplate.Placeholders.Count);
        }

        [TestMethod]
        public void Placeholders_With1Placeholder2Times_Finds1Placeholders()
        {
            var documentTemplate = new DocumentTemplate(@"This is literal line
this is %ThePlaceholder%, dude!
Here it is again: %ThePlaceholder%!
This is the last line.");

            Assert.AreEqual(1, documentTemplate.Placeholders.Count);
        }

        [TestMethod]
        public void Placeholders_With2Placeholders1TimeEach_Finds2Placeholders()
        {
            var documentTemplate = new DocumentTemplate(@"This is literal line
this is %ThePlaceholder%, dude!
Here it is again: %AnotherPlaceholder%!
This is the last line.");

            Assert.AreEqual(2, documentTemplate.Placeholders.Count);
        }

        [TestMethod]
        public void Placeholders_TwoPlaceholdersInALine_FindsBothOfThem()
        {
            var documentTemplate = new DocumentTemplate(@"I say: %This% should be %That%, dude!");

            Assert.AreEqual(2, documentTemplate.Placeholders.Count);
            Assert.AreEqual("This", documentTemplate.Placeholders[0]);
            Assert.AreEqual("That", documentTemplate.Placeholders[1]);
        }

        [TestMethod]
        public void Placeholders_PlaceholderOverNewLineAndCorrectPlaceholder_FindsJustTheCorrectOne()
        {
            var documentTemplate = new DocumentTemplate(@"Mind that: %This is
not a %placeholder!
But %this% is one!");

            Assert.AreEqual(1, documentTemplate.Placeholders.Count);
            Assert.AreEqual("this", documentTemplate.Placeholders[0]);
        }

        [TestMethod]
        [ExpectedException(typeof(UsageOfImplicitNameForPlaceholderSectionException))]
        public void Placeholders_PlaceholderWithNameEnd_ThrowsException()
        {
            new DocumentTemplate("' %Section:End%");    // Everything interesting for this test happens in the constructor
        }

        [TestMethod]
        public void PartTemplates_WithOneParts_MakesPartWithCorrectName()
        {
            const string templateContent =
                @"This is the main part
' === The only part there is
This belongs to /the/ part";
            var documentTemplate = new DocumentTemplate(templateContent);
            
            Assert.AreEqual("The only part there is", documentTemplate.PartTemplates["The only part there is"].Name);
        }

        [TestMethod]
        public void PartTemplates_WithNoPart_FindsNoPart()
        {
            var documentTemplate = new DocumentTemplate(
                @"There is no part in this template.
Everything else is irrelevant
for this test.");

            Assert.AreEqual(0, documentTemplate.PartTemplates.Count);
        }

        [TestMethod]
        [ExpectedException(typeof(KeyNotFoundException))]
        public void PartTemplates_IndexedWithNonExistingPart_ThrowsException()
        {
            var documentTemplate = new DocumentTemplate(
                @"There is a main part
and the part called ExistingPart
but no part called NonExistingPart
' === ExistingPart");

#pragma warning disable 168
            var partTemplate = documentTemplate.PartTemplates["NonExistingPart"];
#pragma warning restore 168
        }

        [TestMethod]
        public void PartTemplates_WithOnePart_Finds1Part()
        {
            var documentTemplate = new DocumentTemplate(
                @"There is one part in this template.
Everything else is irrelevant
for this test.
' === Here begins the part
And that's already part of that part");

            Assert.AreEqual(1, documentTemplate.PartTemplates.Count);
        }

        [TestMethod]
        public void PartTemplates_WithTwoPart_Finds2Parts()
        {
            var documentTemplate = new DocumentTemplate(
                @"There is one part in this template.
Everything else is irrelevant
for this test.
' === Here begins the first part
And that's already part of that part

' === Part #2
And that belongs to Part #2");

            Assert.AreEqual(2, documentTemplate.PartTemplates.Count);
        }
    }
}